package com.miage.itrading.decorateurs;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import com.miage.itrading.entites.Cotation;


public class Indicateurs {

	private Cotation cotation;

	public Indicateurs(Cotation cotation) {
		this.cotation = cotation;
	}

	public Cotation getCotation() {
		return cotation;
	}

	/**
	 * Moyenne mobile simple, qui prend les valeurs de la période précédant (!=
	 * d'une moyenne mobile au sens mathématique)
	 * 
	 * @see http 
	 *      ://en.wikipedia.org/wiki/Moving_average_(finance)#Simple_moving_average
	 * @param periode
	 * @return
	 */
	public List<Float> moyenneMobile(int periode) {

		List<Float> retour = new ArrayList<Float>();

		for (int i = periode; i< cotation.getHistoriques().size(); ++i){
			float res = 0;
			for (int j = i - periode +1 ; j<= i  ; ++j){
				res += cotation.getHistoriques().get(j).getFermeture();
			}
			retour.add(res/periode);
		}
		return retour;
	}

	/**
	 * Moyenne mobile exponentielle
	 * 
	 * @see http://en.wikipedia.org/wiki/Moving_average_(finance)#
	 *      Exponential_moving_average
	 * @param periode
	 * @return
	 */
	public List<Float> moyenneMobileExponentielle(int periode) {
		float alpha = periode +1;
		alpha = 2/alpha;
		float MME;
		List<Float> retour = new ArrayList<Float>();
		for(int i = periode ; i < cotation.getHistoriques().size() ; ++i){
			MME = 0;
			for (int j = i ; j>=0 ; --j){
				MME += alpha * Math.pow((1- alpha),i - j) * cotation.getHistoriques().get(i - (i-j)).getFermeture();
			}
			retour.add(MME);
		}
		return retour;
	}

	/**
	 * Moyenne mobile pondérée
	 * 
	 * @see http://en.wikipedia.org/wiki/Moving_average_(finance)#
	 *      Weighted_moving_average
	 * @param periode
	 * @return
	 */
	public List<Float> moyenneMobilePonderee(int periode) {

		List<Float> retour = new ArrayList<Float>();

		for (int i = periode; i< cotation.getHistoriques().size(); ++i){
			float res = 0;
			int coefficient = 1;
			int denominateur = 0;
			for (int j = i - periode +1 ; j<= i  ; ++j){
				res += cotation.getHistoriques().get(j).getFermeture()*coefficient;
				denominateur +=coefficient;
				coefficient++;
			}
			retour.add(res/denominateur);
		}		
		return retour;
	}

	/**
	 * RSI : Relative Strengh Index
	 * 
	 * @see http://en.wikipedia.org/wiki/Relative_Strength_Index
	 * @param periode
	 * @return valeurs du RSI (ente 0 et 100) sur la période
	 */
	public List<Float> RSI(int periode) {
		List<Float> retour = new ArrayList<Float>();
		periode++;
		for (int i = periode; i< cotation.getHistoriques().size(); ++i){
			float res = 0;
			Vector<Float> varPos = new Vector<Float>();
			Vector<Float> varNeg = new Vector<Float>();
			for (int j = i - periode +1 ; j< i  ; ++j){
				res = cotation.getHistoriques().get(j).getFermeture()-cotation.getHistoriques().get(j+1).getFermeture();
				if(res <0)
				{
					varPos.add(Math.abs(res));
				}
				else
				{
					varNeg.add(res);
				}
			}
			float valPos = 0;
			float valNeg = 0;

			for(Float f : varPos)valPos+=f;
			for(Float f : varNeg)valNeg+=f;
			valPos = valPos/periode;
			valNeg = valNeg/periode;
			float rs = 1+valPos/valNeg;
			float RSI = 100-(100/rs);
			if(valNeg == 0)RSI = 100;
			retour.add(RSI);
		}		
		return retour;
	}

	/**
	 * MACD :
	 * 
	 */
	public List<Float> MACD(int periodeLongue,int periodeCourte)
	{
		
		if (periodeLongue < periodeCourte){
			int tmp = 0;
			tmp = periodeLongue;
			periodeLongue = periodeCourte;
			periodeCourte =tmp;
		}
		
		List<Float> retourInv = new ArrayList<Float>();
		List<Float> retour = new ArrayList<Float>();
		List<Float> MMECourt = moyenneMobileExponentielle(periodeCourte);
		List<Float> MMELong = moyenneMobileExponentielle(periodeLongue);
		
		int incLong= MMELong.size()-1;
		int incCourt= MMECourt.size()-1;
		
		do{
			Float res = (MMECourt.get(incCourt) - MMELong.get(incLong));
			retourInv.add(res);
			incLong --;
			incCourt--;
		}
		while (incLong >= 0 && incCourt >= 0);
		for(int i = retourInv.size()-1; i>=0;--i)retour.add(retourInv.get(i));
		return retour;
	}
	
	/**
	 * momentum
	 * 
	 * @see http://fr.wikipedia.org/wiki/Momentum_(analyse_technique)
	 * @param periode
	 * @return valeurs du momentum
	 */
	public List<Float> momentum(int periode) 
	{

		List<Float> retour = new ArrayList<Float>();

		for (int i = periode; i< cotation.getHistoriques().size(); ++i)
		{
			retour.add(cotation.getHistoriques().get(i).getFermeture()-cotation.getHistoriques().get(i-periode).getFermeture());
		}
		
		return retour;
		
	}
	/**
	 * ROC
	 * 
	 * @see http://en.wikipedia.org/wiki/Rate_of_change_%28technical_analysis%29
	 * @param periode
	 * @return valeurs du ROC
	 */
	public List<Float> ROC(int periode) 
	{

		List<Float> retour = new ArrayList<Float>();

		for (int i = periode; i< cotation.getHistoriques().size(); ++i)
		{
			retour.add(((cotation.getHistoriques().get(i).getFermeture()-cotation.getHistoriques().get(i-periode).getFermeture())*100)/cotation.getHistoriques().get(i-periode).getFermeture());
		}
		
		return retour;
		
	}
	
	
	public void setCotation(Cotation c) {
		this.cotation = c;
	}

}
